package com.lik888.web1.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.benmanes.caffeine.cache.Cache;
import com.lik888.web1.constants.UserContext;
import com.lik888.web1.entity.DTO.EsPageDTO;
import com.lik888.web1.entity.DTO.GoodsTypePageDTO;
import com.lik888.web1.entity.ESTable;
import com.lik888.web1.entity.GoodsTable;
import com.lik888.web1.entity.ImgTable;
import com.lik888.web1.entity.R;
import com.lik888.web1.entity.VO.PageVo;
import com.lik888.web1.entity.nums.Status;
import com.lik888.web1.mapper.GoodsTableMapper;
import com.lik888.web1.mapper.ImgTableMapper;
import com.lik888.web1.service.IGoodsTableService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author author
 * @since 2025-11-05
 */
@Service
@RequiredArgsConstructor
public class GoodsTableServiceImpl extends ServiceImpl<GoodsTableMapper, GoodsTable> implements IGoodsTableService {
    private final GoodsTableMapper goodsTableMapper;
    private final ImgTableMapper imgTableMapper;
    private final Cache<String, GoodsTable> caffeineGoodsTableCache;
    private final StringRedisTemplate redisTemplate;
    private final RedissonClient redisson;
    @Autowired
    private RestHighLevelClient restClient;

//    @PostConstruct
//    public void init(){
//        //初始化GoodsTable 中的goods_look 为0
//        goodsTableMapper.update(null,new LambdaUpdateWrapper<GoodsTable>().set(GoodsTable::getGoodsLook,0));
//    }

    @Override
    @Transactional
    public List<String> SelectType() {
        List<GoodsTable> goodsTables = goodsTableMapper.selectList(new LambdaQueryWrapper<GoodsTable>().select(GoodsTable::getGoodsType));
        Set<String> collect = goodsTables.stream().filter(goodsTable -> goodsTable.getGoodsType() != null).map(GoodsTable::getGoodsType).collect(Collectors.toSet());
        List<String> collect1 = collect.stream().collect(Collectors.toList());
        collect.removeAll(collect1);
        return collect1;
    }

    @Override
    @Transactional
    public R CreateGoods(GoodsTable goodsTable, List<String> goodsImgs) {
        Random random = new Random();
        int randomNum = random.nextInt(1000000);
        //局部变量t 用于判断是否存在ImgTable中是否存在该ID
        int t = 0;
        //查询ImgTable是否GoodsImgid是否存在
        while(t < 1){
            randomNum = random.nextInt(1000000);
            ImgTable imgTable = imgTableMapper.selectOne(new LambdaQueryWrapper<ImgTable>().eq(ImgTable::getGoodsImgid, randomNum));
            if (imgTable == null) {
                goodsTable.setGoodsImgid(randomNum);
                t =1;
                break;
            }
        }
        goodsTable.setGoodsImgid(randomNum);
        //遍历goodsImgs 并添加到ImgTable中
        for (String goodsImg : goodsImgs) {
            ImgTable imgTable = new ImgTable();
            imgTable.setGoodsImgid(randomNum);
            imgTable.setImg(goodsImg);
            imgTableMapper.insert(imgTable);
        }
        //添加到GoodsTable中
        goodsTableMapper.insert(goodsTable);
        return R.ok("添加成功");
    }

    @Override
    public R goodsUp(Long id, Integer status) {
        //查询id相关的商品

        GoodsTable goodsTable = goodsTableMapper.selectOne(new LambdaQueryWrapper<GoodsTable>().eq(GoodsTable::getGoodsId, id));
        if (goodsTable == null) {
            return R.error("商品不存在,可能存在恶意攻击！");
        }
        //判断status的值
        if (status == 0) {
            goodsTable.setGoodsStatus(Status.FROZEN);
        } else if (status == 1) {
            goodsTable.setGoodsStatus(Status.NORMAL);
        } else if (status == 2) {
            goodsTable.setGoodsStatus(Status.UP);
        } else {
            return R.error("Status值错误！可能存在恶意攻击！");
        }

        goodsTableMapper.updateById(goodsTable);
        return R.ok("状态更新成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PageVo<GoodsTable> getTypePage(GoodsTypePageDTO goodsTypePageDTO) {
        Integer pageSize = goodsTypePageDTO.getPageSize();
        Integer page = goodsTypePageDTO.getPage();
        Page<GoodsTable> goodsTablePage = new Page<>(page, pageSize);
        OrderItem orderItem = new OrderItem();
        orderItem.setAsc(true);
        orderItem.setColumn("goods_id");
        goodsTablePage.addOrder(orderItem);
        //执行分页查询
        Page<GoodsTable> goodsTablePage1 = goodsTableMapper.selectPage(goodsTablePage, new LambdaQueryWrapper<GoodsTable>().eq(GoodsTable::getGoodsStatus, Status.NORMAL).eq(GoodsTable::getGoodsType,goodsTypePageDTO.getGoodsTypeName()));
        //将goodsTablePage1 转换为PageVo
        PageVo<GoodsTable> pageVo = new PageVo<>();
        pageVo.setList(goodsTablePage1.getRecords());
        pageVo.setPages(goodsTablePage1.getPages());
        pageVo.setTotal(goodsTablePage1.getTotal());

        return pageVo;
    }

    @Override
    public GoodsTable getDetail(Long id) {
      GoodsTable goodsTable = (GoodsTable) caffeineGoodsTableCache.get("detail:" + id , k -> goodsTableMapper.selectById(id));
      //
        Long UserId = UserContext.getUser();
        if(goodsTable != null){
            //添加浏览列表
            //通过redisson 添加 锁
            RLock lock = redisson.getLock("user:" + UserId + ":" + goodsTable.getGoodsId());
            lock.lock();
            try {
                // 检查用户是否已浏览过该商品
                if (!redisTemplate.opsForSet().isMember("user:" + UserId, goodsTable.getGoodsId().toString())) {
                    // 如果用户未浏览过该商品，则增加浏览量
                    goodsTable.setGoodsLook(goodsTable.getGoodsLook() + 1);
                    goodsTableMapper.updateById(goodsTable);
                }
            } finally {
                lock.unlock();
            }
        }
        return goodsTable;
    }

    @Override
    public PageVo SearchGoods(EsPageDTO esPageDTO) throws IOException {
        String goodsRegion = esPageDTO.getGoodsRegion();
        String goodsType = esPageDTO.getGoodsType();
        Long goodsPrice = esPageDTO.getGoodsPrice();
        String key = esPageDTO.getKey();
        Integer size = esPageDTO.getSize();
        Integer page = esPageDTO.getPage();
        SearchRequest searchRequest = new SearchRequest("1124");
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        List searchFilters = new ArrayList<>();
        //判断key是否为空
        if (key == null || key.isEmpty()) {
             throw new IllegalArgumentException("本架构师警告你 本架构师也是有底线的!");
        }
        boolQueryBuilder.must(QueryBuilders.matchQuery("goods_name", key));
        //判断goodsRegion是否为空
        if (goodsRegion != null && !goodsRegion.isEmpty()) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("goods_region", goodsRegion));
        }
        //判断goodsType是否为空
        if (goodsType != null && !goodsType.isEmpty()) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("goods_type", goodsType));
        }
        //判断goodsPrice是否为空
        if (goodsPrice != null) {
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("goods_price")
                    .gte(goodsPrice)
                    .lte(goodsPrice * 2)
                    //这里本架构师 因为没考虑到 商品价格的范围 所以这里设置为 商品价格的一倍到两倍之间
                    //你没跟我学 商品价格的范围 你可以根据实际情况 调整
            );
        }
        //添加分页查询

        searchRequest.source().query(boolQueryBuilder).from((page - 1) * size).size(size);
        SearchResponse search = restClient.search(searchRequest, RequestOptions.DEFAULT);
        //开始解析结果
        SearchHits hits = search.getHits();
        //获取总条数
        long total = hits.getTotalHits().value;
        //获取命中的文档
        SearchHit[] searchHits = hits.getHits();
        //将命中的文档转换为ESTable
        for (SearchHit searchHit : searchHits) {
            String sourceAsString = searchHit.getSourceAsString();
            ESTable estable = JSON.parseObject(sourceAsString, ESTable.class);
            searchFilters.add(estable);
        }
        //将searchFilters 转换为PageVo
        PageVo<ESTable> pageVo = new PageVo<>();
        pageVo.setList(searchFilters);
        pageVo.setPages((long)page);
        pageVo.setTotal(total);
        return pageVo;
    }
}

//@Test
//void TestBulkRequest() throws Exception{
//        BulkRequest bulkRequest = new BulkRequest();
//    List<TbHotel> list = tbHotelService.list();
//  for (TbHotel tbHotel : list) {
//      HotelDoc hotelDoc = new HotelDoc(tbHotel);
//      bulkRequest.add(
//              new IndexRequest("hotel").id(hotelDoc.getId().toString())
//                      .source(JSON.toJSONString(hotelDoc), XContentType.JSON)
//      );
//  }
//    client.bulk(bulkRequest, RequestOptions.DEFAULT);
//}